/*
 * Copyright (c) 2022 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
import { classToClassFromExist, classToPlain, classToPlainFromExist, deserialize, instanceToInstance, instanceToPlain, plainToClass, plainToClassFromExist, plainToInstance, serialize, Exclude } from "./class-transformer.js";
let count=500;

//将普通javascript对象转换为特定类的实例
function plainToClass_test() {
    let userJson = {
        id: 1,
        firstName: "Johny",
        lastName: "Cage",
        age: 27
    }

    class User {
        id;
        firstName;
        lastName;
        age;

        constructor() {
            this.id = 0;
            this.firstName = "";
            this.lastName = "";
            this.age = 0;
        }

        getName() {
            return this.firstName + ' ' + this.lastName;
        }

        isAdult() {
            return this.age > 36 && this.age < 60;
        }
    }
    let user;
    let start=Date.now();
    for(let i=0;i<count;i++){
        user = plainToClass(User, userJson);
    }
    let end=Date.now();
    print(`class-transformer_plainToClass: ${end-start} ms`)
    if(user.getName()!=='Johny Cage'){
        throw new Error('class-transformer_plainToClass err')
    }
    // print(user.getName());
    // print(user.isAdult() + "");
    // print(JSON.stringify(user))
}

//将普通javascript对象转换为特定类的实例
function plainToInstance_test() {
    const userJson = {
        id: 1,
        firstName: "Johny",
        lastName: "Cage",
        age: 27
    }

    class User {
        id;
        firstName;
        lastName;
        age;

        constructor() {
            this.id = 0;
            this.firstName = "";
            this.lastName = "";
            this.age = 10;
        }
        getName() {
            return this.firstName + ' ' + this.lastName;
        }

        isAdult() {
            return this.age > 36 && this.age < 60;
        }
    }
    let user;
    let start=Date.now();
    for(let i=0;i<count;i++){
        user = plainToInstance(User, userJson);
    }
    let end=Date.now();
    print(`class-transformer_plainToInstance: ${end-start} ms`);
    if(user.getName()!=='Johny Cage'){
        throw new Error('class-transformer_plainToInstance err')
    }
    // print(user.getName());
    // print(user.isAdult() + "");
    // print(JSON.stringify(user));
}

//将类对象转换回普通javascript对象
function classToPlain_test() {
    class User {
        id;
        firstName;
        lastName;
        age;

        constructor() {
            this.id = 0;
            this.firstName = "";
            this.lastName = "";
            this.age = 0;
        }
        getName() {
            return this.firstName + ' ' + this.lastName;
        }

        isAdult() {
            return this.age > 36 && this.age < 60;
        }
    }

    const user = new User();
    user.id = 1;
    user.firstName = "li";
    user.lastName = "si";
    let d;
    let start=Date.now();
    for(let i=0;i<count;i++){
        d = classToPlain(user);
    }
    let end=Date.now();
    print(`class-transformer_classToPlain: ${end-start} ms`);
    if(JSON.stringify(d)!=='{"id":1,"firstName":"li","lastName":"si","age":0}'){
        throw new Error('class-transformer_classToPlain err')
    }
    // print(JSON.stringify(d));
}

//将类对象转换回普通javascript对象
function instanceToPlain_test() {
    class User {
        id;
        firstName;
        lastName;
        password;

        constructor() {
            this.id = 0;
            this.firstName = "";
            this.lastName = "";
            this.password = ""
        }
        getName() {
            return this.firstName;
        }
    }

    let user = new User();
    user.id = 4;
    user.firstName = 'Umed';
    user.lastName = 'Khudoiberdiev';
    user.password = 'imnosuperman';
    let d;
    let start=Date.now();
    for(let i=0;i<count;i++){
        d = instanceToPlain(user)
    }
    let end=Date.now();
    print(`class-transformer_instanceToPlain: ${end-start} ms`)
    if(JSON.stringify(d)!=='{"id":4,"firstName":"Umed","lastName":"Khudoiberdiev","password":"imnosuperman"}'){
        throw new Error('class-transformer_instanceToPlain err')
    }
    // print(JSON.stringify(d))
}


// 将类实例与普通javascript对象合并
function classToPlainFromExist_test() {
    class User {
        id;
        firstName;
        lastName;
        password;
        constructor() {
            this.id = 0;
            this.firstName = "";
            this.lastName = "";
            this.password = "";
        }
        getName() {
            return this.firstName;
        }
    }

    const user = new User();
    user.id = 4;
    user.firstName = 'Umed';
    user.lastName = 'Khudoiberdiev';
    user.password = 'imnosuperman';

    const existUser = { id: 1, age: 27 };
    let d;
    let start=Date.now();
    for(let i=0;i<count;i++){
        d = classToPlainFromExist(user, existUser);
    }
    let end=Date.now();
    print(`class-transformer_classToPlainFromExist: ${end-start} ms`);
    if(JSON.stringify(d)!=='{"id":4,"age":27,"firstName":"Umed","lastName":"Khudoiberdiev","password":"imnosuperman"}'){
        throw new Error('class-transformer_classToPlainFromExist err')
    }
    // print(JSON.stringify(d));
}

//使用已填充的对象（目标类中的实例）将普通对象转换为实例
function plainToClassFromExist_test() {
    class User {
        role;
        constructor() {
            this.role = ""
        }
        getRole() {
            return this.role
        }
    }

    const defaultUser = new User();
    defaultUser.role = 'user';

    const compareValue = { role: "superUser" }
    let mixedUser;
    let start=Date.now();
    for(let i=0;i<count;i++){
        mixedUser = plainToClassFromExist(defaultUser, compareValue);
    }
    let end=Date.now();
    print(`class-transformer_plainToClassFromExist: ${end-start} ms`)
    if(mixedUser.getRole()!=='superUser'){
        throw new Error('class-transformer_plainToClassFromExist err')
    }
    // print(mixedUser.getRole())
    // print(JSON.stringify(mixedUser))
}

// 将类（构造函数）对象转换为新的类（构造器）对象。也适用于数组。
function instanceToInstance_test() {
    class User {
        id;
        firstName;
        lastName;
        password;
        constructor() {
            this.id = 0;
            this.firstName = "";
            this.lastName = "";
            this.password = "";
        }
    }

    const user = new User();
    user.firstName = 'Umed';
    user.lastName = 'Khudoiberdiev';
    user.password = 'imnosuperman';
    let d;
    let start=Date.now();
    for(let i=0;i<count;i++){
        d = instanceToInstance(user)
    }
    let end=Date.now();
    print(`class-transformer_instanceToInstance: ${end-start} ms`);
    if(JSON.stringify(d)!=='{"id":0,"firstName":"Umed","lastName":"Khudoiberdiev","password":"imnosuperman"}'){
        throw new Error('class-transformer_instanceToInstance err')
    }
    // print(JSON.stringify(d));
}

//将类（构造函数）对象转换为纯（文字）对象。
function classToClassFromExist_test() {
    class User {
        id;
        firstName;
        lastName;
        password;
        constructor() {
            this.id = 0;
            this.firstName = "";
            this.lastName = "";
            this.password = "";
        }
    }
    const user = new User();
    user.firstName = 'Umed';
    user.lastName = 'Khudoiberdiev';
    user.password = 'imnosuperman';
    const fromExistUser = new User();
    fromExistUser.id = 1;
    let d; 
    let start=Date.now();
    for(let i=0;i<count;i++){
        d = classToClassFromExist(user, fromExistUser);
    }
    let end=Date.now();
    print(`class-transformer_classToClassFromExist: ${end-start} ms`)
    if(JSON.stringify(d)!=='{"id":0,"firstName":"Umed","lastName":"Khudoiberdiev","password":"imnosuperman"}'){
        throw new Error('class-transformer_classToClassFromExist err')
    }
    // print(JSON.stringify(d));
}

//将对象字符串转换为一个类的实例
function deserialize_test() {
    class User {
        firstName;
        lastName
        // @Exclude()
        password

        constructor() {
            this.firstName = "";
            this.lastName = "";
            this.password = "";
        }
    }
    const plainUser = {
        firstName: 'Umed',
        lastName: 'Khudoiberdiev',
        password: 'imnosuperman',
    };
    let d;
    let start=Date.now();
    for(let i=0;i<count;i++){
        d = deserialize(User, JSON.stringify(plainUser))
    }
    let end=Date.now();
    print(`class-transformer_deserialize: ${end-start} ms`)
    if(JSON.stringify(d)!=='{"firstName":"Umed","lastName":"Khudoiberdiev","password":"imnosuperman"}'){
        throw new Error('class-transformer_deserialize err')
    }
    // print(JSON.stringify(d));
}


//将给定对象序列化为JSON字符串
function serialize_test() {
    class User {
        firstName;
        lastName;
        // @Exclude()
        password;
        constructor() {
            this.firstName = "";
            this.lastName = "";
            this.password = "";
        }
    }

    const user = new User();
    user.firstName = 'Umed';
    user.lastName = 'Khudoiberdiev';
    user.password = 'imnosuperman';
    let plainedUser;
    let start=Date.now();
    for(let i=0;i<count;i++){
        plainedUser = serialize(user);
    }
    let end=Date.now();
    print(`class-transformer_serialize: ${end-start} ms`);
    if(plainedUser!=='{"firstName":"Umed","lastName":"Khudoiberdiev","password":"imnosuperman"}'){
        throw new Error('class-transformer_serialize err')
    }
    // print(plainedUser);
}

let loopCountForPreheat = 1;
for (let i = 0; i < loopCountForPreheat; i++) {
    plainToClass_test();
    plainToInstance_test();
    classToPlain_test();
    instanceToPlain_test();
    classToPlainFromExist_test();
    plainToClassFromExist_test();
    instanceToInstance_test();
    classToClassFromExist_test();
    deserialize_test();
    serialize_test()
}

ArkTools.waitAllJitCompileFinish();

plainToClass_test();
plainToInstance_test();
classToPlain_test();
instanceToPlain_test();
classToPlainFromExist_test();
plainToClassFromExist_test();
instanceToInstance_test();
classToClassFromExist_test();
deserialize_test();
serialize_test()